<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<link rel="stylesheet" href="./css/init.css">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<style>
		html,
		body {
			height: auto
		}

		* {
			margin: 0;
			padding: 0;
			border: 0;
			box-sizing: border-box;
		}

		.all-table-wrap {
			width: 100%;
			position: relative;
			cursor: default;
		}

		.all-table-wrap thead th {
			background-color: #f5f7f9;
			height: 40px;
		}

		.table-style th {
			color: #657180;
			font-size: 13px;
			border: 1px solid #e3e8ee;
		}

		.tr-hover {
			background-color: #ebf7ff !important;
		}

		.table-style tbody tr:nth-child(even) {
			background: #f5f7f9;
		}

		.table-style td {
			padding: 4px 4px;
			color: #657180;
			font-size: 12px;
			text-align: center;
			box-sizing: border-box;
			border: 1px solid #e3e8ee;
		}

		.table-wrap {
			width: 100%;
			word-break: keep-all;
			white-space: nowrap;
			overflow: auto;
			position: relative;
		}
		/* 表头固定 */

		.fixRow-table {
			background-color: #fff;
			position: relative;
			overflow: hidden;
			margin-right: 10px;
			z-index: 22;
		}
		/*真实表格*/

		.table-t {
			width: 100%;
		}

		.table-t thead th {
			padding: 0 4px;
			border-bottom: none;
		}
		/*滚动条的设置*/

		.table-t tbody tr:first-child>td {
			border-top: none;
		}

		.table-wrap::-webkit-scrollbar {
			width: 10px;
			height: 10px;
			background-color: #f5f5f5;
		}
		/*.table-wrap:hover::-webkit-scrollbar {
			width: 10px;
			height: 10px;
			background-color: #f5f5f5;
		}*/

		.table-wrap::-webkit-scrollbar-track {
			-webkit-box-shadow: inset 0 1 6px rgba(0, 0, 0, .3);
			border-radius: 5px;
			background-color: #f5f5f5;
		}

		.table-wrap::-webkit-scrollbar-thumb {
			/* 滚动条中间滚动的颜色 */
			border-radius: 5px;
			-webkit-box-shadow: inset 0 1 6px rgba(0, 0, 0, .3);
			background-color: #d2d2d2;
		}

		.table-wrap::-webkit-scrollbar-corner {
			/* 滚动条中间滚动的颜色 */
			background-color: #f5f5f5;
		}

		.table-fix-tbody-wrap {
			top: -40px;
			position: relative;
		}

		.fixLeftCol-table-wrap-title {
			position: absolute;
			top: 0;
			background-color: #fff;
			z-index: 99;
		}
		/*表体左侧*/

		.fixLeftCol-table-wrap {
			overflow: hidden;
			position: absolute;
			background-color: #fff;
			z-index: 33;
			top: 0;
			box-shadow: 2px 0 6px -2px rgba(0, 0, 0, .2);
		}
		/*
		.fixLeftCol-table-wrap tr {
			box-shadow: 2px 0 6px -2px rgba(0, 0, 0, .2);
		}*/

		.fixRightCol-table-wrap-title {
			position: absolute;
			top: 0;
			right: 10px;
			background-color: #fff;
			z-index: 99;
		}

		.fixRightCol-table-wrap {
			overflow: hidden;
			position: absolute;
			background-color: #fff;
			z-index: 33;
			top: 0;
			right: 10px;
			box-shadow: -2px 0 6px -2px rgba(0, 0, 0, .2);
		}
		/*当数据不是特别多，右边没有滚动条时*/

		.no-left-scroll {
			right: 0;
		}

		.table-left-menu {
			position: absolute;
			z-index: 88888;
			color: #657180;
			font-size: 14px;
			line-height: normal;
			margin: 5px 0;
			padding: 5px 0;
			background-color: #fff;
			box-sizing: border-box;
			border-radius: 4px;
			box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
		}

		.table-left-menu ul li {
			margin: 0;
			padding: 7px 16px;
			clear: both;
			color: #657180;
			font-size: 12px!important;
			white-space: nowrap;
			list-style: none;
			cursor: pointer;
			transition: background .2s ease-in-out;
		}

		.table-left-menu ul li:hover {
			background: #f3f3f3;
		}
	</style>
</head>

<body>
	<div id="app">
		<div style="width:1300px;margin:16px auto">
			<Tabs value="name1" type="card" :animated="false">
				<Tab-pane label="全部预约（3）" name="name1">
					<!--<i-Table stripe :columns="tableColumns" :data="tableData"></i-Table>-->
					<vue-fix-table :table-Height="tableHeight" :table-Data="tableData" :table-Columns="tableColumns" :left-Menu="leftMenu" @t-dblclick="tableClick">
					</vue-fix-table>
				</Tab-pane>
				<Tab-pane label="重拍（2）" name="name2">
					<!--<i-Table stripe :columns="tableColumns" :data="tableData"></i-Table>-->
					<vue-fix-table :table-Height="tableHeight" :table-Data="tableData" :table-Columns="tableColumns" @t-dblclick="tableClick">
					</vue-fix-table>
				</Tab-pane>
			</Tabs>


		</div>
	</div>

</body>
<template id="vue-fix-table">

	<!--表格-->
	<div class="all-table-wrap" :style="{height:tableHeight+'px'}">
		<!--固定顶部表头-->
		<div class="fixRow-table" ref="tableTop">
			<table class="table-style">
				<thead>
					<tr>
						<th v-for="(col,index) in tableColumnsFix.allCol">
							<div :style="{width:tableTdWidth[index]+'px'}">
								{{col.title}}
							</div>
						</th>
					</tr>
				</thead>
			</table>
		</div>
		<!--固定左侧表头-->
		<template v-if="(tableData.length>0&&tableColumnsFix.fixLeftCol.length>0)">
			<div class="fixLeftCol-table-wrap-title">
				<table class="table-style">
					<thead>
						<tr>
							<th v-for="(th,index) in  tableColumnsFix.fixLeftCol">
								<div :style="{width:tableTdWidth[index]+'px'}">
									{{th.title}}
								</div>
							</th>
						</tr>
					</thead>
				</table>
			</div>
			<!--固定左侧的数据-->
			<div class="fixLeftCol-table-wrap" ref="tableLeft" :style="{height:tableFixHeight}">
				<table class="table-style">
					<thead>
						<tr>
							<th v-for="(th,index) in  tableColumnsFix.fixLeftCol">
								<div :style="{width:tableTdWidth[index]+'px'}">
									{{th.title}}
								</div>
							</th>
						</tr>
					</thead>
					<tbody>
						<tr v-for="(rowData,index) in tableData" :class="{'tr-hover':nowHover==index}" @mouseover="trHover(index)" @mouseout="trOut">
							<td v-for="th in tableColumnsFix.fixLeftCol">{{rowData[th.key]}}</td>
						</tr>
					</tbody>
				</table>
			</div>
		</template>

		<!--真实表格-->
		<div class="table-fix-tbody-wrap">
			<div class="table-wrap" @scroll="tableScroll" ref="table" :style="{height:tableHeight+'px'}">
				<table class="table-style table-t" ref="tableTrue">
					<thead>
						<tr>
							<th v-for="col in tableColumnsFix.allCol">
								{{col.title}}
							</th>
						</tr>
					</thead>
					<tbody>
						<!--如果没有数据-->
						<template v-if="tableData.length==0">
							<tr>
								<td :colspan="tableColumnsFix.allCol.length" style="text-align:center">暂无数据</td>
							</tr>
						</template>
						<template v-for="(rowData,index) in tableData">
							<tr @dblclick="dblclick(rowData,index)" :class="{'tr-hover':nowHover==index}" @mouseover="trHover(index)" @mouseout="trOut">
								<template v-for="col in tableColumnsFix.allCol">
									<template v-if="rowData.rowspan">
										<template v-if="tdRowspan(rowData,col)!=0">
											<td @click="tdClick(rowData,col,$event)" v-html="renderTd(rowData,col)" :rowspan="tdRowspan(rowData,col)" :style="tdStyle(rowData,col)">
											</td>
										</template>
									</template>
									<template v-else>
										<td @click="tdClick(rowData,col,$event)" :style="tdStyle(rowData,col)" v-html="renderTd(rowData,col)">
										</td>
									</template>
								</template>
							</tr>
						</template>
					</tbody>
				</table>
			</div>
		</div>
		<!--固定右侧表头-->
		<template v-if="(tableData.length>0&&tableColumnsFix.fixRightCol.length>0)">
			<div class="fixRightCol-table-wrap-title" :class="{'no-left-scroll':noLeftScroll}">
				<table class="table-style">
					<thead>
						<tr>
							<th v-for="(th,index) in tableColumnsFix.fixRightCol">
								<div :style="{width:tableTdWidth[index]+'px'}">
									{{th.title}}
								</div>
							</th>
						</tr>
					</thead>
				</table>
			</div>
			<!--固定右侧-->
			<div class="fixRightCol-table-wrap" ref="tableRight" :style="{height:tableFixHeight}" :class="{'no-left-scroll':noLeftScroll}">
				<table class="table-style">
					<thead>
						<tr>
							<th v-for="(th,index) in tableColumnsFix.fixRightCol">
								<div :style="{width:tableTdWidth[index]+'px'}">
									{{th.title}}
								</div>
							</th>
						</tr>
					</thead>
					<tbody>
						<tr v-for="(rowData,index) in tableData" :class="{'tr-hover':nowHover==index}" @mouseover="trHover(index)" @mouseout="trOut">
							<td v-for="th in tableColumnsFix.fixRightCol" v-html="renderTd(rowData,th)"></td>
						</tr>
					</tbody>
				</table>
			</div>
		</template>
		<!--end -->
		<template v-if="showLeftMenu">
			<div class="table-left-menu" :style="leftMenuStyle">
				<ul>
					<li v-for="(key,index) in leftMenu" @click="leftMenuOptClick(index)">{{key}}</li>
				</ul>
			</div>
		</template>
	</div>

</template>
<script src="http://cdn.bootcss.com/vue/2.1.10/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="http://unpkg.com/iview/dist/styles/iview.css">
<!-- 引入组件库 -->
<script src="http://unpkg.com/iview/dist/iview.min.js"></script>

<script>
	"use strict"
	Vue.component('vue-fix-table', {
		template: '#vue-fix-table',
		props: {
			tableHeight: Number, //表格高度
			tableData: Array, //表格数据
			tableColumns: Array, //表格表头
			leftMenu: Array
		},
		data: function () {
			return {
				showLeftMenu: false,
				leftMenuStyle: {
					top: 0,
					left: 0
				},
				nowClick: {},
				noLeftScroll: '',
				tableFixHeight: '0px',
				tableTdWidth: [],
				nowHover: -1 //当前经过的行 
			}
		},
		watch: {
			//表格数据更新完毕，固定表格
			tableData: function (val, oldVal) {
				this.$nextTick(function () {
					this.checkFix();
					this.CalcTableFixHeight();
				})
			},
			tableColumns: function (val, oldVal) {
				this.$nextTick(function () {
					this.checkFix();
					this.CalcTableFixHeight();
				})
			}
		},
		mounted: function () {
			this.checkFix();
			this.CalcTableFixHeight();
			//监听窗口改变事件
			var self = this;
			window.addEventListener('resize', function () {
				self.checkFix();
				self.CalcTableFixHeight();
			});
			window.addEventListener('click', (e) => {
				if (!this.$refs.tableTrue.contains(e.target)) {
					this.showLeftMenu = false;
				}
			})
		},
		computed: {
			// 固定列的数据
			tableColumnsFix: function () {
				var fixLeftCol = [];
				var fixRightCol = [];
				var unFixCol = [];
				for (var i = 0; i < this.tableColumns.length; i++) {
					var thisData = this.tableColumns[i];
					if (thisData.fixed && thisData.fixed == 'left') {
						fixLeftCol.push(thisData);
					} else if (thisData.fixed && thisData.fixed == 'right') {
						fixRightCol.push(thisData);
					} else {
						unFixCol.push(thisData);
					}
				}
				unFixCol.unshift.apply(unFixCol, fixLeftCol);
				unFixCol.push.apply(unFixCol, fixRightCol);
				return {
					fixLeftCol: fixLeftCol, //固定在左侧
					fixRightCol: fixRightCol, //固定在右侧
					allCol: unFixCol //固定表头
				};
			}
		},
		methods: {
			// 固定左侧
			tableScroll: function () {
				this.showLeftMenu = false;
				requestAnimationFrame(this.tableScrollMethod);
				// this.tableScrollMethod();
			},
			tableScrollMethod: function () {
				// 表头滚动
				this.$refs.tableTop && (this.$refs.tableTop.scrollLeft = this.$refs.table.scrollLeft);
				// 左侧滚动
				this.$refs.tableLeft && (this.$refs.tableLeft.scrollTop = this.$refs.table.scrollTop);
				//右侧滚动
				this.$refs.tableRight && (this.$refs.tableRight.scrollTop = this.$refs.table.scrollTop);
			},
			checkFix: function () {
				var ths = this.$refs.tableTrue.querySelectorAll('th');
				console.log(this.$refs.tableTrue)
				for (var i = 0; i < this.tableColumns.length; i++) {
					//设置每个列的宽度
					if (ths.item(i).clientWidth == 0) {
						continue;
					}
					this.$set(this.tableTdWidth, i, ths.item(i).clientWidth);
				}
			},
			//计算表格高度
			CalcTableFixHeight: function () {
				if (this.$refs.tableTrue.clientHeight < this.tableHeight) {
					//当表格数据不足以充满总高度
					this.noLeftScroll = true;
					this.tableFixHeight = this.$refs.tableTrue.clientHeight + 'px';
				} else {
					this.noLeftScroll = false;
					this.tableFixHeight = this.tableHeight - 10 + 'px';
				}
			},
			// 双击事件
			dblclick: function (rowData, index) {
				this.$emit('t-dblclick', rowData, index)
			},
			// Hover改变事件
			trHover: function (index) {
				this.nowHover = index;
			},
			trOut: function () {
				this.nowHover = -1;
			},
			tdStyle(rowData, th) {
				if (th.style) {
					return th.style(rowData);
				} else {
					return;
				}
			},
			renderTd: function (rowData, th) {
				if (th.render) {
					return th.render(rowData);
				} else {
					return rowData[th.key];
				}

			},
			tdRowspan(rowData, th) {
				if (th.key in rowData.rowspan) {
					return rowData.rowspan[th.key]
				} else {
					return null;
				}
			},
			tdClick(rowData, th, event) {
				this.nowClick = {
					rowData: rowData,
					th: th
				}
				// console.log(event)
				this.showLeftMenu = th.needLeftMenu;
				this.leftMenuStyle.top = event.layerY + 'px';
				this.leftMenuStyle.left = event.layerX + 'px';
				// console.log(this.leftMenuStyle)
			},
			leftMenuOptClick(index) {
				this.$emit('menuopt-click', index, this.nowClick)
			}
		}
	})


	var app = new Vue({
		el: '#app',
		data: {
			tableHeight: 300,
			leftMenu: ['请假', '取消假期', '详细'],
			tableColumns: [{
				title: '姓名',
				key: 'name',
				fixed: 'left' //固定
			}, {
				title: '手机',
				key: 'phone',
				// fixed: 'left'
			}, {
				title: '年龄',
				key: 'age',
				color(rowData) {
					if (rowData.age % 2 == 0) {
						return '#c2c2c2';
					} else {
						return '#f2c2f2';
					}

				}
			}, {
				title: '地址1',
				key: 'address1',
				needLeftMenu: true
				// fixed: 'left'
			}, {
				title: '地址2',
				key: 'address2'
			}, {
				title: '地址3',
				key: 'address3'
			}, {
				title: '地址4',
				key: 'address4'
			}, {
				title: '地址5',
				key: 'address5'
			}, {
				title: '地址6',
				key: 'address6'
			}, {
				title: '地址7',
				key: 'address7',
				fixed: 'right',
				render: function (rowData) {
					return '<button></button>'
				}
			}, {
				title: '地址8',
				key: 'address8',
				// fixed: 'right'
			}],
			tableData: [{
				name: 'st' + 1,
				phone: '15502515852',
				age: 10,
				address1: '地址1**********************',
				address2: '地址2',
				address3: '地址3',
				address4: '地址4',
				address5: '地址5',
				address6: '出卖我的爱 逼着我离开',
				address7: '当初是你要分开 分开就分开',
				address8: '现在又要用真爱把我哄回来 ',
				rowspan: {
					name: 3,
					phone: 2
				}
			}, {
				name: 'st' + 2,
				phone: '15502515852',
				age: 11,
				address1: '地址1**********************',
				address2: '地址2',
				address3: '地址3',
				address4: '地址4',
				address5: '地址5',
				address6: '出卖我的爱 逼着我离开 ',
				address7: '当初是你要分开 分开就分开',
				address8: '现在又要用真爱把我哄回来12312312312312312312312312312312 ',
				rowspan: {
					name: 0,
					phone: 0
				}
			}, {
				name: 'st' + 2,
				phone: '15502515852',
				age: 11,
				address1: '地址1**********************',
				address2: '地址2',
				address3: '地址3',
				address4: '地址4',
				address5: '地址5',
				address6: '出卖我的爱 逼着我离开 ',
				address7: '当初是你要分开 分开就分开',
				address8: '现在又要用真爱把我哄回来 现在又要用真爱把我哄回来12312312312312312312312312312312',
				rowspan: {
					name: 0
				}
			}],
		},
		mounted: function () {
			this.getData();

		},
		methods: {
			getData: function () {
				// 模拟获取表格数据
				var tableData = [];
				for (var i = 0; i < 100; i++) {
					var data = {
						name: 'st' + i,
						phone: '15502515852',
						age: 10 + i,
						address1: '地址1**********************' + i,
						address2: '地址2',
						address3: '地址3',
						address4: '地址4',
						address5: '地址5',
						address6: '出卖我的爱 逼着我离开 最后知道真相的我眼泪掉下来 出卖我的爱 你背了良心债 就算付出再多感情也再买不回来',
						address7: '当初是你要分开 分开就分开',
						address8: '现在又要用真爱把我哄回来 现在又要用真爱把我哄回来12312312312312312312312312312312',
					};
					tableData.push(data);
				}
				setTimeout(() => {
					this.tableData = tableData;
				}, 500);
			},
			tableClick: function (data, index) {
				console.log(data);
			},
		}
	});
</script>

</html>